package com.axter.test.js;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Scanner;

/**
 * 关于页面
 * Created by axter on 2016/6/2.
 *
 * 参考地址
 *   http://mobile.51cto.com/aprogram-452011.htm
 *   http://blog.csdn.net/leehong2005/article/details/11808557
 */
public class AboutActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_about);

        WebView webview = (WebView) findViewById(R.id.webview);
        webview.getSettings().setJavaScriptEnabled(true);
//        webview.addJavascriptInterface(new JsInterface(this),"JsInterface");
        webview.setWebChromeClient(
                new WebChromeClient() {
                    boolean mIsInjectedJS;

                    @Override
                    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                        toast(message);
                        try {
                            JSONObject jsonObj = new JSONObject(message);
                            String interfaceName = jsonObj.getString("obj");
                            String methodName = jsonObj.getString("func");
                            JSONArray argsArray = jsonObj.getJSONArray("args");
                            Object[] args = null;
                            if (null != argsArray) {
                                int count = argsArray.length();
                                if (count > 0) {
                                    args = new Object[count];

                                    for (int i = 0; i < count; ++i) {
                                        args[i] = argsArray.get(i);
                                    }
                                }
                            }

                            if (invokeJSInterfaceMethod(result, interfaceName, methodName, args)) {
                                return true;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        result.cancel();
                        return false;
                    }

                    @Override
                    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                        result.confirm();
                        return true;
                    }

                    @Override
                    public void onProgressChanged(WebView view, int newProgress) {
                        if (newProgress <= 25) {
                            mIsInjectedJS = false;
                        } else if (!mIsInjectedJS) {
                            try {
                                InputStream is = AboutActivity.this.getAssets().open("ext.js");
                                String script = convertStreamToString(is);
                                view.loadUrl("javascript:" + script);
                                mIsInjectedJS = true;
                                Log.d("WebChromeClient", " inject js interface completely on progress " + newProgress);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        super.onProgressChanged(view, newProgress);
                    }
                }
        );
        webview.loadUrl("file:///android_asset/test.html");
    }

    private boolean invokeJSInterfaceMethod(JsPromptResult result,
                                            String interfaceName, String methodName, Object[] args) {

        boolean succeed = false;
        final Object obj = new JsInterface(this);
        if (null == obj) {
            result.cancel();
            return false;
        }

        Class<?>[] parameterTypes = null;
        int count = 0;
        if (args != null) {
            count = args.length;
        }

        if (count > 0) {
            parameterTypes = new Class[count];
            for (int i = 0; i < count; ++i) {
                parameterTypes[i] = getClassFromJsonObject(args[i]);
            }
        }

        try {
            Method method = obj.getClass().getMethod(methodName, parameterTypes);
            Object returnObj = method.invoke(obj, args); // 执行接口调用
            boolean isVoid = returnObj == null || returnObj.getClass() == void.class;
            String returnValue = isVoid ? "" : returnObj.toString();
            result.confirm(returnValue); // 通过prompt返回调用结果
            succeed = true;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        result.cancel();
        return succeed;
    }

    private Class<?> getClassFromJsonObject(Object obj) {
        Class<?> cls = obj.getClass();

        // js对象只支持int boolean string三种类型
        if (cls == Integer.class) {
            cls = Integer.TYPE;
        } else if (cls == Boolean.class) {
            cls = Boolean.TYPE;
        } else {
            cls = String.class;
        }

        return cls;
    }

    public String convertStreamToString(java.io.InputStream is) {
        String s = "";
        try {
            Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A");
            if (scanner.hasNext()) s = scanner.next();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s;
    }

    public void toast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
}
